import requests
import json
import logging
import time
import base64
import hashlib
import hmac
from typing import Dict, Optional, Union
import sys
import os

# 添加项目根目录到路径，以便导入 app 模块
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

try:
    from app.utils.dpop_token_generator import get_fresh_mercari_token, is_mercari_token_expired
    DPOP_GENERATOR_AVAILABLE = True
except ImportError:
    DPOP_GENERATOR_AVAILABLE = False
    print("⚠️ DPoP Token 生成器不可用，将使用静态 Token")

try:
    from app.utils.traffic_monitor import traffic_monitor
    TRAFFIC_MONITOR_AVAILABLE = True
except ImportError:
    TRAFFIC_MONITOR_AVAILABLE = False
    print("⚠️ 流量监控不可用")

# 配置日志 - 关闭详细日志
logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class MercariAPI:
    def __init__(self,  user_agent: Optional[str] = None, dpop_token: Optional[str] = None, auto_refresh_token: bool = True):
        self.base_url = 'https://api.mercari.jp'
        # self.cookies = cookies
        self.auto_refresh_token = auto_refresh_token  # 是否自动刷新 Token

        # 初始化 DPoP Token
        if dpop_token:
            self.dpop_token = dpop_token
        elif DPOP_GENERATOR_AVAILABLE and auto_refresh_token:
            print("🔄 使用自动生成的 DPoP Token")
            self.dpop_token = get_fresh_mercari_token()
            print(f"✅ 生成的 DPoP Token: {self.dpop_token[:50]}...")
        else:
            # 使用默认的静态 Token（兜底方案）
            self.dpop_token = 'eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7ImNydiI6IlAtMjU2Iiwia3R5IjoiRUMiLCJ4IjoidEF4N0JwS185WmZ2TDYyUVp1ZUJralZXbGh5ZE9SYzFjZld1Y2VjRzFPbyIsInkiOiJmamZyR2c4c3hjQ2RLMkVkV0hGc2VsNnRickNMYmhOdmJUT2F2ajZQYTBvIn19.eyJpYXQiOjE3NTIzMDc4NjMsImp0aSI6ImM1NjY4Yzc3LTdjODUtNGJlOS1iM2NhLWM3NjdkZDE1MWQxNCIsImh0dSI6Imh0dHBzOi8vYXBpLm1lcmNhcmkuanAvdjIvZW50aXRpZXM6c2VhcmNoIiwiaHRtIjoiUE9TVCIsInV1aWQiOiI5MWUzMjM5Yi0zYzFlLTQwN2UtYjE0OC1lNjE1MmU5YTNhMTEifQ.iMzSq83fE-iTVR4H06C946bsd32gl1zXdMZhZNgTgnPiFAVOpj1eYQIz1E5wKiD7PBm0TZIB-ahwyvIsYT1T0g'
            logger.warning("⚠️ 使用静态 DPoP Token，建议启用自动刷新功能")
        self.headers = {
            'Content-Type': 'application/json',
            'User-Agent': user_agent or 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
            # 'Cookie': cookies,  # 正确设置Cookie
            'Accept': 'application/json, text/plain, */*',
            'Accept-Encoding': 'gzip, deflate, br, zstd',
            'Accept-Language': 'ja',
            'Origin': 'https://jp.mercari.com',
            'Referer': 'https://jp.mercari.com/',
            'Sec-Ch-Ua': '"Not)A;Brand";v="8", "Chromium";v="138", "Google Chrome";v="138"',
            'Sec-Ch-Ua-Mobile': '?0',
            'Sec-Ch-Ua-Platform': '"Windows"',
            'Sec-Fetch-Dest': 'empty',
            'Sec-Fetch-Mode': 'cors',
            'Sec-Fetch-Site': 'cross-site',
            'X-Country-Code': 'KR',
            'X-Platform': 'web',
            'priority': 'u=1, i'
        }

        # 添加DPoP令牌到请求头
        if self.dpop_token:
            self.headers['DPoP'] = self.dpop_token
        self.session = requests.Session()
        self.session.headers.update(self.headers)
        # 添加重试机制
        self.session.mount('https://', requests.adapters.HTTPAdapter(max_retries=3))

    def _estimate_request_size(self, url: str, method: str, data=None, params=None) -> int:
        """估算请求大小"""
        try:
            # 计算URL大小
            size = len(url.encode('utf-8'))

            # 计算请求头大小
            for key, value in self.headers.items():
                size += len(f"{key}: {value}\r\n".encode('utf-8'))

            # 计算请求体大小
            if data:
                if isinstance(data, dict):
                    size += len(json.dumps(data, ensure_ascii=False).encode('utf-8'))
                else:
                    size += len(str(data).encode('utf-8'))

            # 计算查询参数大小
            if params:
                import urllib.parse
                size += len(urllib.parse.urlencode(params).encode('utf-8'))

            return size
        except Exception:
            return 1000  # 默认估算值

    def _record_traffic_sync(self, url: str, method: str, request_size: int, response_size: int, success: bool, task_type: str = "mercari_api"):
        """同步记录流量统计并打印"""
        try:
            if TRAFFIC_MONITOR_AVAILABLE:
                # 记录到流量监控系统
                traffic_monitor.record_traffic_sync(
                    proxy_url=None,
                    request_size=request_size,
                    response_size=response_size,
                    task_type=task_type,
                    success=success,
                    url=url
                )

            # 打印流量统计信息
            total_size = request_size + response_size
            status = "✅ 成功" if success else "❌ 失败"
            print(f"📊 流量统计: {method} {url[:50]}...")
            print(f"   📤 请求大小: {request_size} 字节 ({request_size/1024:.1f} KB)")
            print(f"   📥 响应大小: {response_size} 字节 ({response_size/1024:.1f} KB)")
            print(f"   📊 总流量: {total_size} 字节 ({total_size/1024:.1f} KB)")
            print(f"   🎯 状态: {status}")
            print(f"   🏷️ 任务类型: {task_type}")

        except Exception as e:
            print(f"⚠️ 流量统计记录失败: {e}")

    def _ensure_valid_token(self) -> None:
        """确保 DPoP Token 有效，如果过期则自动刷新"""
        if not self.auto_refresh_token or not DPOP_GENERATOR_AVAILABLE:
            return

        try:
            if self.dpop_token and is_mercari_token_expired(self.dpop_token):
                logger.info("🔄 DPoP Token 已过期，正在自动刷新...")
                old_token = self.dpop_token[:20] + "..."
                self.dpop_token = get_fresh_mercari_token()
                self.headers['DPoP'] = self.dpop_token
                self.session.headers.update(self.headers)
                logger.info(f"✅ DPoP Token 刷新成功: {old_token} -> {self.dpop_token[:20]}...")
            elif not self.dpop_token:
                logger.info("🔄 DPoP Token 为空，正在生成新的 Token...")
                self.dpop_token = get_fresh_mercari_token()
                self.headers['DPoP'] = self.dpop_token
                self.session.headers.update(self.headers)
                logger.info("✅ 新的 DPoP Token 生成完成")
        except Exception as e:
            logger.error(f"❌ DPoP Token 刷新失败: {e}")
            # 刷新失败时继续使用现有 Token

    def search_products(self, keyword: str, sort: str = 'SORT_CREATED_TIME', order: str = 'ORDER_DESC', limit: int = 20) -> Optional[Dict]:
        """
        搜索Mercari商品
        :param keyword: 搜索关键词
        :param sort: 排序字段，默认为'SORT_CREATED_TIME'
        :param order: 排序方向，默认为'ORDER_DESC'
        :param limit: 结果数量，默认为20
        :return: 搜索结果字典或None
        """
        endpoint = '/v2/entities:search'
        url = f'{self.base_url}{endpoint}'

        # 构建完整的payload - 参照mercari_client.py的结构
        payload = {
            "userId": "",
            "pageSize": limit,
            "pageToken": "",
            "searchSessionId": f"{int(time.time())}{hashlib.md5(keyword.encode()).hexdigest()[:8]}",
            "source": "BaseSerp",
            "indexRouting": "INDEX_ROUTING_UNSPECIFIED",
            "thumbnailTypes": [],
            "searchCondition": {
                "keyword": keyword,
                "excludeKeyword": "",
                "sort": sort,
                "order": order,
                "status": [],
                "sizeId": [],
                "categoryId": [],
                "brandId": [],
                "sellerId": [],
                "priceMin": 0,
                "priceMax": 0,
                "itemConditionId": [],
                "shippingPayerId": [],
                "shippingFromArea": [],
                "shippingMethod": [],
                "colorId": [],
                "hasCoupon": False,
                "attributes": [],
                "itemTypes": [],
                "skuIds": [],
                "shopIds": [],
                "excludeShippingMethodIds": []
            },
            "serviceFrom": "suruga",
            "withItemBrand": False,
            "withItemSize": False,
            "withItemPromotions": False,
            "withItemSizes": False,
            "withShopname": False,
            "useDynamicAttribute": False,
            "withSuggestedItems": False,
            "withOfferPricePromotion": False,
            "withProductSuggest": False,
            "withParentProducts": False,
            "withProductArticles": False,
            "withSearchConditionId": False,
            "withAuction": False,
            "laplaceDeviceUuid": "6bfeff14dad2abab10fc65a0f2a79f85"
        }

        try:
            # 确保 DPoP Token 有效
            self._ensure_valid_token()

            print(f'🔍 搜索商品: {keyword}, 排序: {sort} {order}')
            print(f'请求URL: {url}')

            # 如果提供了DPoP令牌，则添加到请求头
            if self.dpop_token:
                self.headers['DPoP'] = self.dpop_token
                print(f'✅ 已添加DPoP令牌到请求头: {self.dpop_token[:30]}...')
            else:
                print('⚠️ 没有DPoP令牌')
            
            print(f'📤 发送请求到: {url}')
            print(f'📋 请求头包含DPoP: {"DPoP" in self.headers}')

            # 计算请求大小
            request_size = self._estimate_request_size(url, "POST", data=payload)

            response = self.session.post(url, json=payload, timeout=10)  # 使用json参数自动处理序列化

            print(f'📥 响应状态码: {response.status_code}')
            if response.status_code != 200:
                print(f'📄 响应头: {dict(response.headers)}')
                print(f'📝 响应内容: {response.text[:500]}...')
            
            response.raise_for_status()  # 抛出HTTP错误
            result = response.json()

            # 计算响应大小并记录流量统计
            response_size = len(response.content)
            self._record_traffic_sync(url, "POST", request_size, response_size, True, "mercari_search")

            # 统计搜索结果
            product_count = 0
            if 'items' in result:
                product_count = len(result['items'])
            elif 'data' in result:
                product_count = len(result['data'])

            print(f'✅ Mercari API调用成功，状态码: {response.status_code}，获取商品数量: {product_count}')
            return result
        except requests.exceptions.HTTPError as e:
            # 记录失败的流量统计
            response_size = len(response.content) if 'response' in locals() and response else 0
            self._record_traffic_sync(url, "POST", request_size, response_size, False, "mercari_search")

            print(f'❌ Mercari API HTTP错误: {e}，状态码: {response.status_code if "response" in locals() else "未知"}')
            if 'response' in locals() and response:
                print(f'错误响应内容: {response.text[:500]}...')
                if response.status_code == 400:
                    print('请求格式错误，请检查请求参数和格式')
                elif response.status_code == 401:
                    print('认证错误，可能需要更新DPoP令牌或其他认证信息')
                    # 如果是认证错误，尝试刷新 Token
                    if self.auto_refresh_token and DPOP_GENERATOR_AVAILABLE:
                        print("🔄 检测到认证错误，尝试强制刷新 DPoP Token...")
                        try:
                            self.dpop_token = get_fresh_mercari_token()
                            self.headers['DPoP'] = self.dpop_token
                            self.session.headers.update(self.headers)
                            print("✅ DPoP Token 强制刷新完成，请重试请求")
                        except Exception as refresh_error:
                            print(f"❌ 强制刷新 DPoP Token 失败: {refresh_error}")
                elif response.status_code == 403:
                    print('权限错误，可能需要更新DPoP令牌或检查认证信息')
            return None
        except requests.exceptions.RequestException as e:
            # 记录失败的流量统计
            self._record_traffic_sync(url, "POST", request_size, 0, False, "mercari_search")

            print(f'❌ Mercari API请求异常: {e}')
            return None
        except json.JSONDecodeError as e:
            # 记录失败的流量统计
            response_size = len(response.content) if 'response' in locals() and response else 0
            self._record_traffic_sync(url, "POST", request_size, response_size, False, "mercari_search")

            print(f'❌ Mercari API JSON解析错误: {e}')
            if 'response' in locals() and response:
                print(f'响应内容: {response.text[:300]}...')
            return None

print('🚀 开始运行Mercari API搜索...')
if __name__ == '__main__':
    # 测试自动 DPoP Token 刷新功能
    print("🧪 测试模式：自动 DPoP Token 刷新")

    # 初始化API客户端（启用自动刷新）
    print("📝 初始化 Mercari API 客户端（自动刷新模式）...")
    mercari_api = MercariAPI(auto_refresh_token=True)

    # 搜索商品 - 使用自定义关键词
    print("🔍 开始搜索商品...")
    results = mercari_api.search_products(
        keyword='鬼灭',
        sort='SORT_CREATED_TIME',
        order='ORDER_DESC',
        limit=10
    )

    if results:
        # 提取并打印商品信息

        print(results)
        items = []
        if 'items' in results:
            items = results['items']
        elif 'data' in results:
            items = results['data']

        if items:
            print(f'✅ 找到{len(items)}个商品:')
            # for i, item in enumerate(items[:5], 1):  # 只显示前5个商品
                # name = item.get("name", "未知商品")
                # price = item.get("price", "未知价格")
                # status = item.get("status", "未知状态")
                # print(f'{i}. 商品名称: {name}')
                # print(f'   价格: {price}日元')
                # print(f'   状态: {status}')
                # print('   ---')
                # print(item)
        else:
            print('⚠️ 响应中没有找到商品数据')
            print(f'响应结构: {list(results.keys()) if isinstance(results, dict) else "非字典类型"}')
    else:
        print('❌ 搜索失败，请检查日志获取详细信息')

    # 显示流量统计总结
    print('\n' + '='*60)
    print('📊 流量统计总结')
    print('='*60)
    if TRAFFIC_MONITOR_AVAILABLE:
        try:
            import asyncio
            # 获取今日流量统计
            async def get_stats():
                daily_stats = await traffic_monitor.get_daily_stats()
                return daily_stats

            try:
                loop = asyncio.get_event_loop()
                if loop.is_running():
                    print('📈 流量统计: 请运行 python scripts/check_traffic_stats.py 查看详细统计')
                else:
                    daily_stats = loop.run_until_complete(get_stats())
                    if daily_stats.get('request_count', 0) > 0:
                        print(f'📊 今日总请求: {daily_stats.get("request_count", 0)}')
                        print(f'📊 今日总流量: {daily_stats.get("total_mb", 0)} MB')
                        print(f'📊 成功率: {daily_stats.get("success_rate", 0)}%')
                        avg_size = daily_stats.get('total_bytes', 0) / daily_stats.get('request_count', 1)
                        print(f'📊 平均请求大小: {avg_size:.0f} 字节 ({avg_size/1024:.1f} KB)')
                    else:
                        print('📊 暂无流量统计数据')
            except RuntimeError:
                # 如果无法获取事件循环，创建新的
                new_loop = asyncio.new_event_loop()
                asyncio.set_event_loop(new_loop)
                try:
                    daily_stats = new_loop.run_until_complete(get_stats())
                    if daily_stats.get('request_count', 0) > 0:
                        print(f'📊 今日总请求: {daily_stats.get("request_count", 0)}')
                        print(f'📊 今日总流量: {daily_stats.get("total_mb", 0)} MB')
                        print(f'📊 成功率: {daily_stats.get("success_rate", 0)}%')
                        avg_size = daily_stats.get('total_bytes', 0) / daily_stats.get('request_count', 1)
                        print(f'📊 平均请求大小: {avg_size:.0f} 字节 ({avg_size/1024:.1f} KB)')
                    else:
                        print('📊 暂无流量统计数据')
                finally:
                    new_loop.close()
        except Exception as e:
            print(f'⚠️ 获取流量统计失败: {e}')
    else:
        print('⚠️ 流量监控不可用，无法显示统计信息')

    print('='*60)

print('程序运行完毕')